package pres.moling.auth.service;

import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.util.MimeTypeUtils;
import org.springframework.util.ObjectUtils;

import java.io.IOException;

/**
 * 登录过滤器
 */
public class AuthLoginFilter extends UsernamePasswordAuthenticationFilter {

    /**
     * 构造方法的参数都可以从容器获取，所以这里也直接注册到容器自动构造
     * 继承了UsernamePasswordAuthenticationFilter，后续我们要用它替换默认的UsernamePasswordAuthenticationFilter
     * 构造函数中，指定了：
     * 登陆成功和失败时的处理方法
     * 记住我功能的组件
     * 登陆使用的路径
     * attemptAuthentication方法中规定了登陆流程：
     * 如果Content-Type是Json，则从Body中获取请求参数，否则从Form表单中获取
     * 从Session的Attribute中获取之前保存的验证码，和用户提供的验证码进行比对
     * 把用户提供的rememberMe字段放到request的Attribute中，供后续MyRememberMeServices获取
     * 结尾部分来自父类，照抄过来的
     */
    private final ObjectMapper objectMapper = new ObjectMapper();

    public AuthLoginFilter(AuthenticationManager authenticationManager,
                           AuthenticationHandler authenticationHandler,
                           AuthRememberMeServices rememberMeServices) throws Exception {
        super(authenticationManager);
        setAuthenticationFailureHandler(authenticationHandler);
        setAuthenticationSuccessHandler(authenticationHandler);
        //rememberMe
        setRememberMeServices(rememberMeServices);
        //登陆使用的路径
        setFilterProcessesUrl("/sys/user/login");
    }

    private static boolean isContentTypeJson(HttpServletRequest request) {
        final String contentType = request.getContentType();
        return AuthenticationHandler.APPLICATION_JSON_CHARSET_UTF_8.equalsIgnoreCase(contentType) || MimeTypeUtils.APPLICATION_JSON_VALUE.equalsIgnoreCase(contentType);
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) {

        if (!HttpMethod.POST.name().equalsIgnoreCase(request.getMethod())) {
            throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
        }
        String username = null;
        String password = null;
        String verifyCode = null;
        String rememberMe = null;
        if (isContentTypeJson(request)) {
            try {
                JSONObject map = JSONObject.parseObject(request.getInputStream(),JSONObject.class);
                username = map.getString(getUsernameParameter());
                password = map.getString(getPasswordParameter());
//                verifyCode = map.get(VERIFY_CODE_KEY);
//                rememberMe = map.get(MyRememberMeServices.REMEMBER_ME_KEY);
            } catch (IOException e) {
                e.printStackTrace();
            }
        } else {
            username = obtainUsername(request);
            password = obtainPassword(request);
//            verifyCode = request.getParameter(VERIFY_CODE_KEY);
            rememberMe = request.getParameter(AuthRememberMeServices.REMEMBER_ME_KEY);
        }
        //校验验证码
//        final String vc = (String) request.getSession().getAttribute(VERIFY_CODE_KEY);
//        if (vc == null) {
//            throw new BadCredentialsException("验证码不存在,请先获取验证码");
//        } else if (verifyCode == null || "".equals(verifyCode)) {
//            throw new BadCredentialsException("请输入验证码");
//        } else if (!vc.equalsIgnoreCase(verifyCode)) {
//            throw new BadCredentialsException("验证码错误");
//        }

        //将 rememberMe 状态存入 attr中
        if (!ObjectUtils.isEmpty(rememberMe)) {
            request.setAttribute(AuthRememberMeServices.REMEMBER_ME_KEY, rememberMe);
        }

        username = (username != null) ? username.trim() : "";
        password = (password != null) ? password : "";
        UsernamePasswordAuthenticationToken authRequest = UsernamePasswordAuthenticationToken.unauthenticated(username, password);
        // Allow subclasses to set the "details" property
        setDetails(request, authRequest);

        return this.getAuthenticationManager().authenticate(authRequest);
    }
}
